const std = @import("std");
const cz_std = @import("cz_std.zig");
const lexer = @import("lexer.zig");
const parser = @import("parser.zig");
const codegen = @import("codegen.zig");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const args = try std.process.argsAlloc(allocator);
    defer std.process.argsFree(allocator, args);

    if (args.len < 2) {
        try printUsage();
        return;
    }

    const command = args[1];

    if (std.mem.eql(u8, command, "--help") or std.mem.eql(u8, command, "-h")) {
        try printUsage();
        return;
    }

    if (std.mem.eql(u8, command, "--version") or std.mem.eql(u8, command, "-v")) {
        try printVersion();
        return;
    }

    // 源文件路径
    const source_path = command;

    // 解析其他参数
    var output_path: ?[]const u8 = null;
    var emit_zig = false;
    var verbose = false;
    var debug_mode = false;

    var i: usize = 2;
    while (i < args.len) : (i += 1) {
        const arg = args[i];

        if (std.mem.eql(u8, arg, "-o") and i + 1 < args.len) {
            output_path = args[i + 1];
            i += 1;
        } else if (std.mem.eql(u8, arg, "--emit-zig")) {
            emit_zig = true;
        } else if (std.mem.eql(u8, arg, "--verbose")) {
            verbose = true;
        } else if (std.mem.eql(u8, arg, "--debug")) {
            debug_mode = true;
        }
    }

    // 默认输出文件名
    const default_output = "output";
    const final_output = output_path orelse default_output;

    if (verbose) {
        std.debug.print("CZ 编译器 v0.1.0\n", .{});
        std.debug.print("CZ Compiler v0.1.0\n", .{});
        std.debug.print("编译: {s}\n", .{source_path});
        std.debug.print("Compiling: {s}\n", .{source_path});
        std.debug.print("输出: {s}\n", .{final_output});
        std.debug.print("Output: {s}\n", .{final_output});
    }

    // 编译流程
    try compile(allocator, source_path, final_output, emit_zig, verbose);
}

fn compile(
    allocator: cz_std.Allocator,
    source_path: []const u8,
    output_path: []const u8,
    emit_zig: bool,
    verbose: bool,
) !void {
    // 1. 读取源文件
    if (verbose) {
        std.debug.print("[1/4] 读取源文件...\n", .{});
        std.debug.print("[1/4] Reading source file...\n", .{});
    }
    const source = std.fs.cwd().readFileAlloc(source_path, allocator, @enumFromInt(10 * 1024 * 1024)) catch |err| {
        std.debug.print("错误：无法读取文件 '{s}': {}\n", .{source_path, err});
        std.debug.print("Error: Cannot read file '{s}': {}\n", .{source_path, err});
        return err;
    };
    defer allocator.free(source);

    // 2. 词法分析
    if (verbose) {
        std.debug.print("[2/4] 词法分析...\n", .{});
        std.debug.print("[2/4] Lexical analysis...\n", .{});
    }
    const tokens = lexer.tokenize(allocator, source) catch |err| {
        std.debug.print("错误：词法分析失败: {}\n", .{err});
        std.debug.print("Error: Lexical analysis failed: {}\n", .{err});
        return err;
    };
    defer allocator.free(tokens);

    if (verbose) {
        std.debug.print("  发现 {d} 个标记\n", .{tokens.len});
        std.debug.print("  Found {d} tokens\n", .{tokens.len});
    }

    // 3. 语法分析
    if (verbose) {
        std.debug.print("[3/4] 语法分析...\n", .{});
        std.debug.print("[3/4] Parsing...\n", .{});
    }
    const ast = parser.parse(allocator, tokens) catch |err| {
        std.debug.print("错误：语法分析失败: {}\n", .{err});
        std.debug.print("Error: Parsing failed: {}\n", .{err});
        return err;
    };
    defer ast.deinit(allocator);

    if (verbose) {
        std.debug.print("  解析了 {d} 个顶层声明\n", .{ast.items.len});
        std.debug.print("  Parsed {d} top-level declarations\n", .{ast.items.len});
    }

    // 4. 代码生成
    if (verbose) {
        std.debug.print("[4/4] 代码生成...\n", .{});
        std.debug.print("[4/4] Code generation...\n", .{});
    }
    const zig_code = codegen.generate(allocator, ast) catch |err| {
        std.debug.print("错误：代码生成失败: {}\n", .{err});
        std.debug.print("Error: Code generation failed: {}\n", .{err});
        return err;
    };
    defer allocator.free(zig_code);

    // 输出 Zig 代码
    const zig_output_path = try std.fmt.allocPrint(allocator, "{s}.zig", .{output_path});
    defer allocator.free(zig_output_path);

    std.fs.cwd().writeFile(.{ .sub_path = zig_output_path, .data = zig_code }) catch |err| {
        std.debug.print("错误：无法写入文件 '{s}': {}\n", .{zig_output_path, err});
        std.debug.print("Error: Cannot write file '{s}': {}\n", .{zig_output_path, err});
        return err;
    };

    if (emit_zig or verbose) {
        std.debug.print("已生成 Zig 代码: {s}\n", .{zig_output_path});
        std.debug.print("Generated Zig code: {s}\n", .{zig_output_path});
    }

    // 调用 Zig 编译器编译生成的代码
    if (!emit_zig) {
        if (verbose) {
            std.debug.print("使用 Zig 编译...\n", .{});
            std.debug.print("Compiling with Zig...\n", .{});
        }
        
        const result = try std.process.Child.run(.{
            .allocator = allocator,
            .argv = &[_][]const u8{
                "zig",
                "build-exe",
                zig_output_path,
                "-O",
                "ReleaseFast",
            },
        });
        defer allocator.free(result.stdout);
        defer allocator.free(result.stderr);

        if (result.term.Exited != 0) {
            std.debug.print("错误：Zig 编译失败\n", .{});
            std.debug.print("Error: Zig compilation failed\n", .{});
            std.debug.print("{s}\n", .{result.stderr});
            return error.CompilationFailed;
        }

        std.debug.print("✓ 编译成功: {s}\n", .{output_path});
        std.debug.print("✓ Compilation successful: {s}\n", .{output_path});
    }
}

fn printUsage() !void {
    const usage =
        \\CZ 编译器 (czc) v0.1.0
        \\CZ Compiler (czc) v0.1.0
        \\
        \\用法 / USAGE:
        \\    czc <source.cz> [选项 / OPTIONS]
        \\
        \\选项 / OPTIONS:
        \\    -o <file>       指定输出文件名 / Specify output file name
        \\    --emit-zig      只输出生成的 Zig 代码 / Output generated Zig code only
        \\    --verbose       显示详细编译信息 / Show detailed compilation information
        \\    --debug         使用调试符号编译 / Compile with debug symbols
        \\    --help, -h      显示此帮助信息 / Show this help message
        \\    --version, -v   显示版本信息 / Show version information
        \\
        \\示例 / EXAMPLES:
        \\    czc hello.cz -o hello
        \\    czc program.cz --emit-zig --verbose
        \\
    ;

    std.debug.print("{s}", .{usage});
}

fn printVersion() !void {
    std.debug.print("CZ 编译器 (czc) v0.1.0\n", .{});
    std.debug.print("CZ Compiler (czc) v0.1.0\n", .{});
}

test "basic test" {
    try std.testing.expectEqual(1, 1);
}
